package com.example.xxpk.service.usersignin;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.xxpk.bo.DailySignInInfo;
import com.example.xxpk.bo.DailySignInRecord;
import com.example.xxpk.bo.NewUserSignInInfo;
import com.example.xxpk.bo.SignInResult;
import com.example.xxpk.mapper.*;
import com.example.xxpk.pojo.*;
import com.example.xxpk.service.userprops.IUserPropsService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;

@Service
@RequiredArgsConstructor
public class UserSignInServiceImpl extends ServiceImpl<UserSignInMapper, UserSignIn> implements IUserSignInService {

    private final SginInRewardsMapper sginInRewardsMapper;

    private final UsersMapper usersMapper;

    private final OutiftsMapper outiftsMapper;

    private final UserOutiftsMapper userOutiftsMapper;

    private final PropsMapper propsMapper;

    private final UserSignInMapper userSignInMapper;

    private final IUserPropsService userPropsService;
    //新玩家七日签到
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SignInResult newUserSignIn(Integer userId) {

        // 检查今天是否已经签到
        LocalDate today = LocalDate.now();
        LambdaQueryWrapper<UserSignIn> checkWrapper = new LambdaQueryWrapper<>();
        checkWrapper.eq(UserSignIn::getUserId, userId)
                .eq(UserSignIn::getSignType, "new_user")
                .eq(UserSignIn::getSignDate, today);
        UserSignIn todaySignIn = this.getOne(checkWrapper);

        if (todaySignIn != null) {
            throw new RuntimeException("您今天已经签到过了，不能重复签到！");
        }

        // 查询玩家是否已经完成新玩家签到
        LambdaQueryWrapper<UserSignIn> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserSignIn::getUserId, userId)
                .eq(UserSignIn::getSignType, "new_user")
                .orderByDesc(UserSignIn::getTotalSignDays)
                .last("LIMIT 1");
        UserSignIn lastSignIn = this.getOne(wrapper);

        if (lastSignIn != null && lastSignIn.getTotalSignDays() >= 7) {
            throw new RuntimeException("恭喜您获得所有奖励！");
        }

        // 计算签到天数
        int signDays = lastSignIn == null ? 1 : lastSignIn.getTotalSignDays() + 1;

        // 插入签到记录
        UserSignIn signIn = new UserSignIn();
        signIn.setUserId(userId);
        signIn.setSignType("new_user");
        signIn.setSignDate(LocalDate.now());
        signIn.setTotalSignDays(signDays);
        this.save(signIn);

        // 获取签到奖励
        LambdaQueryWrapper<SginInRewards> rewardWrapper = new LambdaQueryWrapper<>();
        rewardWrapper.eq(SginInRewards::getType, 1)
                .eq(SginInRewards::getNewUserDay, signDays); // 根据新用户签到天数查询奖励
        SginInRewards reward = sginInRewardsMapper.selectOne(rewardWrapper);
        if (reward == null) {
            throw new RuntimeException("签到失败，请稍后再试");
        }

        // 发放奖励
        grantReward(userId, reward.getRewardType(),reward.getRewardCount(),reward.getRewardId());

        // 返回结果
        SignInResult result = new SignInResult();
        result.setSignDays(signDays);
        result.setReward(reward);
        return result;
    }

    //日常签到
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SignInResult dailySignIn(Integer userId) {

        // 获取今日日期
        LocalDate today = LocalDate.now();

        // 检查今日是否已经签到
        LambdaQueryWrapper<UserSignIn> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserSignIn::getUserId, userId)
                .eq(UserSignIn::getSignType, "daily")
                .eq(UserSignIn::getSignDate, today); // 修改为 LocalDate 类型比较
        if (this.count(wrapper) > 0) {
            throw new RuntimeException("今日已签到");
        }

        // 插入签到记录
        SignInResult result = insertSignInRecordAndGetReward(userId, "daily", today);
        if (result == null) {
            throw new RuntimeException("签到失败，请稍后再试");
        }
        SginInRewards reward = result.getReward();
        // 发放奖励
        grantReward(userId, reward.getRewardType(),reward.getRewardCount(),reward.getRewardId());

        return result;
    }


    /**
     * 补签
     *
     * @param userId   用户 ID
     * @param signDate 补签日期（格式：yyyy-MM-dd）
     * @return 补签结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SignInResult makeUpSignIn(Integer userId, String signDate) {
        // 1. 检查用户是否有足够的补签道具
        Users user = usersMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        if (user.getSignInPrpos() < 1) {
            throw new RuntimeException("补签道具不足");
        }

        // 2. 解析补签日期
        LocalDate date = LocalDate.parse(signDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        // 3. 检查是否已经补签过该日期
        LambdaQueryWrapper<UserSignIn> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserSignIn::getUserId, userId)
                .eq(UserSignIn::getSignType, "daily")
                .eq(UserSignIn::getSignDate, date);
        if (this.count(wrapper) > 0) {
            throw new RuntimeException("该日期已经签到，无需补签");
        }

        // 4. 消耗补签道具
        user.setSignInPrpos(user.getSignInPrpos() - 1);
        usersMapper.updateById(user);

        // 5. 插入签到记录
        SignInResult result = insertSignInRecordAndGetReward(userId, "daily", date);
        SginInRewards reward = result.getReward();

        // 6. 发放奖励
        grantReward(userId, reward.getRewardType(),reward.getRewardCount(),reward.getRewardId());

        return result;
    }


    /**
     * 查询新用户签到信息
     * @param userId 用户 ID
     * @return 新用户签到信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public NewUserSignInInfo getNewUserSignInInfo(Integer userId) {
        // 查询用户的新用户签到记录
        LambdaQueryWrapper<UserSignIn> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserSignIn::getUserId, userId)
                .eq(UserSignIn::getSignType, "new_user")
                .orderByDesc(UserSignIn::getTotalSignDays)
                .last("LIMIT 1");
        UserSignIn lastSignIn = this.getOne(wrapper);

        int totalSignDays = lastSignIn == null ? 0 : lastSignIn.getTotalSignDays();
        boolean isCompleted = totalSignDays >= 7;

        // 获取所有新用户签到奖励
        LambdaQueryWrapper<SginInRewards> rewardWrapper = new LambdaQueryWrapper<>();
        rewardWrapper.eq(SginInRewards::getType, 1);
        List<SginInRewards> rewards = sginInRewardsMapper.selectList(rewardWrapper);

        // 判断今天是否已经签到
        boolean canSignToday = true;
        if (lastSignIn != null && lastSignIn.getSignDate().isEqual(LocalDate.now())) {
            canSignToday = false;
        }

        // 封装新用户签到信息
        NewUserSignInInfo signInInfo = new NewUserSignInInfo();
        signInInfo.setCompleted(isCompleted);
        signInInfo.setTotalSignDays(totalSignDays);
        signInInfo.setRewards(rewards);
        signInInfo.setCanSignToday(canSignToday);
        return signInInfo;
    }


    /**
     * 获取本月日常签到信息
     * @param userId 用户 ID
     * @return 包含本月签到信息及当天是否已签到的对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public DailySignInInfo getDailySignInInfo(Integer userId) {
        LocalDate now = LocalDate.now();
        LocalDate startOfMonth = now.withDayOfMonth(1);
        LocalDate endOfMonth = now.withDayOfMonth(now.lengthOfMonth());

        // 查询本月用户日常签到记录
        LambdaQueryWrapper<UserSignIn> signInWrapper = new LambdaQueryWrapper<>();
        signInWrapper.eq(UserSignIn::getUserId, userId)
                .eq(UserSignIn::getSignType, "daily")
                .ge(UserSignIn::getSignDate, startOfMonth)
                .le(UserSignIn::getSignDate, endOfMonth);
        List<UserSignIn> userSignIns = userSignInMapper.selectList(signInWrapper);
        int signCount = userSignIns.size();

        // 查询本月日常签到奖励信息
        List<DailySignInRecord> records = sginInRewardsMapper.selectDailySignInRecords(startOfMonth, endOfMonth);

        // 为每条记录设置签到状态
        for (DailySignInRecord record : records) {
            LocalDate date = record.getDate();
            boolean isSigned = userSignIns.stream().anyMatch(signIn -> signIn.getSignDate().equals(date));

            if (date.isBefore(now)) {
                if (isSigned) {
                    record.setStatus("signedIn");
                } else {
                    record.setStatus("canMakeUp");
                }
            } else if (date.equals(now)) {
                if (isSigned) {
                    record.setStatus("signedIn");
                } else {
                    record.setStatus("canSign");
                }
            } else {
                record.setStatus("NotArrived");
            }
        }
        // 判断今天是否已签到
        boolean isSignedToday = userSignIns.stream().anyMatch(signIn -> signIn.getSignDate().equals(now));

        DailySignInInfo dailySignInInfo = new DailySignInInfo();
        dailySignInInfo.setSignedToday(isSignedToday);
        dailySignInInfo.setSignInRecords(records);
        dailySignInInfo.setSignDays(signCount);
        return dailySignInInfo;
    }


    @Transactional(rollbackFor = Exception.class)
    public SignInResult insertSignInRecordAndGetReward(Integer userId, String signType, LocalDate date) {
        YearMonth currentMonth = YearMonth.from(date);
        // 查询当月已签到次数
        LambdaQueryWrapper<UserSignIn> monthlyWrapper = new LambdaQueryWrapper<>();
        monthlyWrapper.eq(UserSignIn::getUserId, userId)
                .eq(UserSignIn::getSignType, "daily")
                .ge(UserSignIn::getSignDate, currentMonth.atDay(1))
                .le(UserSignIn::getSignDate, currentMonth.atEndOfMonth());
        int monthlySignCount = (int) this.count(monthlyWrapper) + 1;

        // 插入签到记录
        UserSignIn signIn = new UserSignIn();
        signIn.setUserId(userId);
        signIn.setSignType(signType);
        signIn.setSignDate(date);
        signIn.setTotalSignDays(monthlySignCount);
        this.save(signIn);

        // 获取签到奖励
        LambdaQueryWrapper<SginInRewards> rewardWrapper = new LambdaQueryWrapper<>();
        rewardWrapper.eq(SginInRewards::getType, 2)
                .eq(SginInRewards::getDate, date);
        SginInRewards reward = sginInRewardsMapper.selectOne(rewardWrapper);
        if (reward == null) {
            throw new RuntimeException("该日期的签到奖励未配置");
        }
        // 返回结果
        SignInResult result = new SignInResult();
        result.setSignDays(monthlySignCount);
        result.setReward(reward);
        return result;
    }


    //奖励分发
    @Transactional(rollbackFor = Exception.class)
    public void grantReward(Integer userId, Integer rewardType,Integer rewardCount,Integer rewardsId) {
        Users user = usersMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        switch (rewardType) {
            case 1: // 灵石
                user.setDiamond(user.getDiamond() + rewardCount);
                usersMapper.updateById(user);
                break;
            case 2: // 极品灵石
                user.setPremiumDiamond(user.getPremiumDiamond() + rewardCount);
                usersMapper.updateById(user);
                break;
            case 3: // 通用道具
                user.setUniversalProps(user.getUniversalProps() + rewardCount);
                usersMapper.updateById(user);
                break;
            case 4: // 补签道具
                user.setSignInPrpos(user.getSignInPrpos() + rewardCount);
                usersMapper.updateById(user);
                break;
            case 5: // 游戏道具
                Props props = propsMapper.selectById(rewardsId);
                if (props == null) {
                    throw new RuntimeException("道具不存在");
                }
                userPropsService.obtainProps(userId,rewardsId,rewardCount);
                break;
            case 6: // 装扮
                Outifts outifts = outiftsMapper.selectById(rewardsId);
                if (outifts == null) {
                    throw new RuntimeException("装扮不存在");
                }
                QueryWrapper<UserOutifts> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("user_id", userId)
                        .eq("outifts_id", outifts.getOutiftsId());
                UserOutifts userOutifts = userOutiftsMapper.selectOne(queryWrapper);

                if(userOutifts != null ){
                    if ("1".equals(userOutifts.getStatus())) {
                        user.setSignInPrpos(user.getSignInPrpos() + 10);
                        usersMapper.updateById(user);
                    }
                }
                userOutifts.setUserId(userId);
                userOutifts.setOutiftsId(rewardsId);
                userOutifts.setCategory(outifts.getCategory());
                Date now = new Date();
                Instant instant = now.toInstant();
                LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
                userOutifts.setAcquiredTime(localDateTime);
                userOutifts.setLevel(1);
                userOutifts.setExperience(0);
                userOutifts.setStatus(1); // 已拥有
                userOutiftsMapper.insert(userOutifts);
                break;
            default:
                // 其他情况暂不处理
                break;
        }
    }
}